﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="PoolMember.cs" company="">
//   
// </copyright>
// <summary>
//   Defines the PoolMember type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace F5.BigIp.LocalTrafficManager.Interfaces
{
    using System;

    /// <summary>
    ///     The pool member.
    /// </summary>
    public class PoolMember : NotifyPropertyChanged, IPoolMember
    {
        #region Fields

        /// <summary>
        ///     The last update.
        /// </summary>
        private DateTime lastUpdate;

        /// <summary>
        ///     The statistics.
        /// </summary>
        private PoolMemberStatistics statistics;

        /// <summary>
        ///     The status.
        /// </summary>
        private PoolMemberStatus status;

        #endregion

        #region Constructors and Destructors

        /// <summary>Initializes a new instance of the <see cref="PoolMember"/> class.</summary>
        /// <param name="loadBalancer">The LoadBalancer.</param>
        /// <param name="pool">The pool.</param>
        /// <param name="address">The address.</param>
        /// <param name="port">The port.</param>
        /// <exception cref="ArgumentNullException">Arguments cannot be null.</exception>
        /// <exception cref="ArgumentOutOfRangeException">Port number must be between 0 and 65,535.</exception>
        public PoolMember(LoadBalancer loadBalancer, IPool pool, string address, int port)
        {
            if (loadBalancer == null)
            {
                throw new ArgumentNullException("loadBalancer");
            }

            if (pool == null)
            {
                throw new ArgumentNullException("pool");
            }

            if (string.IsNullOrEmpty(address))
            {
                throw new ArgumentNullException("address");
            }

            if (this.Port < 0 || this.Port > 65535)
            {
                throw new ArgumentOutOfRangeException("port", "Port numbers must be greater than or equal to zero and less than 65,535.");
            }

            this.LoadBalancer = loadBalancer;
            this.Pool = pool;
            this.Address = address;
            this.Port = port;
            this.LastUpdate = DateTime.Now;
        }

        #endregion

        #region Public Events

        /// <summary>
        ///     The connections closed.
        /// </summary>
        public event EventHandler ConnectionsClosed;

        /// <summary>
        ///     The waiting for connections to close.
        /// </summary>
        public event EventHandler WaitingForConnectionsToClose;

        #endregion

        #region Public Properties

        /// <summary>
        ///     Gets or sets the address.
        /// </summary>
        public string Address { get; set; }

        /// <summary>
        ///     Gets or sets the LoadBalancer.
        /// </summary>
        public LoadBalancer LoadBalancer { get; set; }

        /// <summary>
        ///     Gets or sets the last update.
        /// </summary>
        public DateTime LastUpdate
        {
            get
            {
                return this.lastUpdate;
            }

            set
            {
                this.lastUpdate = value;
                this.OnPropertyChanged();
            }
        }

        /// <summary>
        ///     Gets the name.
        /// </summary>
        public string Name
        {
            get
            {
                return this.Address.Contains("/") ?
                    this.Address.Split('/')[2] :
                    this.Address; // TODO: (backward compatibility) consider moving into implementation class
            }
        }

        /// <summary>
        ///     Gets the path.
        /// </summary>
        public string Path
        {
            get
            {
                return this.Address.Contains("/") ?
                    this.Address.Split('/')[1] :
                    this.Address; // TODO: (backward compatibility) consider moving into implementation class
            }
        }

        /// <summary>
        ///     Gets or sets the pool.
        /// </summary>
        public IPool Pool { get; set; }

        /// <summary>
        ///     Gets or sets the port.
        /// </summary>
        public int Port { get; set; }

        /// <summary>
        ///     Gets or sets the statistics.
        /// </summary>
        public PoolMemberStatistics Statistics
        {
            get
            {
                return this.statistics;
            }

            set
            {
                this.statistics = value;
                this.OnPropertyChanged();
            }
        }

        /// <summary>
        ///     Gets or sets the status.
        /// </summary>
        public PoolMemberStatus Status
        {
            get
            {
                return this.status;
            }

            set
            {
                if (this.status == value)
                {
                    return;
                }

                this.status = value;
                this.OnPropertyChanged();
            }
        }

        #endregion

        //public void WaitForConnectionsToClose(int timeout, int pollingInterval)
        //{
        //    double elapsed = 0;

        //    var timeoutInMilliseconds = TimeSpan.FromMinutes(timeout).TotalMilliseconds;

        //    if (this.WaitingForConnectionsToClose != null)
        //    {
        //        this.WaitingForConnectionsToClose(this, EventArgs.Empty);
        //    }

        //    do
        //    {
        //        this.Statistics = this.GetStatistics();

        //        if (this.Statistics.CurrentConnections <= 0)
        //        {
        //            continue;
        //        }

        //        Thread.Sleep(pollingInterval);

        //        elapsed += pollingInterval;
        //    }
        //    while (this.Statistics.CurrentConnections > 0 && elapsed < timeoutInMilliseconds);

        //    if (this.ConnectionsClosed != null)
        //    {
        //        this.ConnectionsClosed(this, EventArgs.Empty);
        //    }
        //}
    }
}